package com.cdks.wuxiu.api.controller;

import javax.annotation.Resource;
import javax.validation.Valid;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cdks.wuxiu.api.component.aliyun.CloudStorage;
import com.cdks.wuxiu.api.component.chuanglan.FlashMobileLoginUtil;
import com.cdks.wuxiu.api.component.constant.Constant;
import com.cdks.wuxiu.api.component.constant.ScoreEnum;
import com.cdks.wuxiu.api.model.common.AuthParam;
import com.cdks.wuxiu.api.model.dto.KmsgDataDTO;
import com.cdks.wuxiu.api.model.param.AccountFastLoginParam;
import com.cdks.wuxiu.api.model.param.AccountSignLoginParam;
import com.cdks.wuxiu.api.model.param.AccountSmsLoginParam;
import com.cdks.wuxiu.api.model.param.LoginParam;
import com.cdks.wuxiu.api.model.vo.LoginVO;
import com.cdks.wuxiu.api.model.vo.UserInfoVO;
import com.cdks.wuxiu.api.service.AccountService;
import com.cdks.wuxiu.api.service.AuthService;
import com.cdks.wuxiu.api.service.CallService;
import com.cdks.wuxiu.api.service.CommonService;
import com.cdks.wuxiu.api.service.MessageService;
import com.cdks.wuxiu.api.service.ScoreService;
import com.cdks.wuxiu.api.service.SystemService;
import com.cdks.wuxiu.api.service.UserService;
import com.cdks.wuxiu.api.util.HttpUtils;
import com.cdks.wuxiu.api.util.TimeUtils;
import com.cdks.wuxiu.common.component.constant.ApiCodeEnum;
import com.cdks.wuxiu.common.exception.ApiException;
import com.cdks.wuxiu.common.model.api.ApiResult;
import com.cdks.wuxiu.common.util.ServletUtils;
import com.cdks.wuxiu.entity.message.ChatPrivateData;
import com.cdks.wuxiu.entity.mysql.BannedUserInfo;
import com.cdks.wuxiu.entity.mysql.CallSheetInfo;
import com.cdks.wuxiu.entity.mysql.UserBaseInfo;
import com.cdks.wuxiu.entity.mysql.UserLoginInfo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;


@Slf4j
@Api(tags = "登录")
@RestController
@RequestMapping("/account")
public class AccountController {
    @Resource
    private AuthService authService;
    @Resource
    private CommonService commonService;
    @Resource
    private SystemService systemService;  
    @Resource
    private AccountService accountService;      
    @Resource
    private UserService userService;
    @Resource
    private CallService callService;
    @Resource
    private ScoreService scoreService;    
    @Resource
    private MessageService messageService;  


    private CallSheetInfo getBusyCall(long userId)
    {
        CallSheetInfo sheet  = callService.getBusyCallAnyUser(userId, userId);
        if (sheet == null)
        {
            return null;
        }

        //已接通话单直接返回
        if (sheet.getStatus() > Constant.CALL_STATUS_WAITING)
        {
            return sheet;
        }

        //被叫的待接听在kmsg登录时返回
        if (sheet.getAnswerId() == userId)
        {
            return null;
        }

        //返回主叫未接通的定向通话待接听
        if ((sheet.getType() == Constant.CALL_TYPE_SINGLE_AUDIO) || (sheet.getType() == Constant.CALL_TYPE_SINGLE_VIDEO))
        {
            return sheet;
        }

        //挂断主叫未接通的一键倾诉通话。挂断失败则说明被叫已接听（一键倾诉只有主叫能挂断，所以不可能是被叫挂断），需要重新获取话单信息
        sheet.setRemark("系统：" + userId + "登录时挂断");
        sheet.setStatus(Constant.CALL_STATUS_STOPPED + Constant.CALL_ENDTYPE_ERROR);
        if (callService.hangupCallByStatus(sheet, Constant.CALL_STATUS_WAITING) == 0)
        {
            callService.hangupRandCall(sheet, Constant.CALL_ENDTYPE_ERROR, "通话已结束");
        }
        else
        {
            return callService.getSheetByUcid(sheet.getUcid());
        }

        return null;
    }

    private LoginVO login(UserBaseInfo userInfo, String phone, LoginParam param) {
        long now  = TimeUtils.getTimeSecond();
        if ((userInfo != null) && ((now - userInfo.getCreateTime()) < 86400) && (userInfo.getStatus() == Constant.ACCOUNT_STATUS_DELETED))
        {
            throw new ApiException(10, "账号注销后24小时内禁止注册，若因误操作请联系官方微信：xinsuwx");
        }

        BannedUserInfo info  = accountService.checkAccount(param.getUdid(), phone);
        if (info != null)
        {
            //永久封禁
            if (info.getExpire() == 0)
            {
                throw new ApiException(10, "您的账号因" + info.getReason() + "已被封禁，若有疑问请咨询官方微信：xinsuwx");
            }

            //解封时间未到
            if (info.getExpire() > now)
            {
                throw new ApiException(10, "您的账号因" + info.getReason() + "已被封禁，" + TimeUtils.getLocalDateTime("yyyy-MM-dd HH:mm:ss", info.getExpire()) + " 前不可使用。若有疑问请咨询官方微信：xinsuwx");
            }

            throw new ApiException(10, "禁止登录，若有疑问请咨询官方微信：xinsuwx");
        }

        String ip  = ServletUtils.getIpAddress();
        boolean isNew  = (userInfo == null) || (userInfo.getStatus() == Constant.ACCOUNT_STATUS_DELETED);
        if (isNew)
        {
            // 未注册 自动注册
            userInfo  = accountService.userRegister(phone, param.getBranch(), param.getUdid());
            if (userInfo == null)
            {
                throw new ApiException(ApiCodeEnum.SERVICE_ERROR);
            }

            //新用户注册发送指南
            ChatPrivateData data;
            data  = new ChatPrivateData();
            data.setTitle("使用指南");
            data.setContent("恭喜您成功注册舞秀。“舞秀”是一个绿色正规的一对一语音聊天社交平台。在这里你可以找一个聊得来的陌生人放心地倾诉心事，也可以通过接听通话、发布自己的舞蹈作品、邀请好友注册赚钱哦~~。");
            data.setScheme("xinsu://web?url=https://wuxiu.cdks.net/web/guide/introduce.html");
            messageService.sendSystemMessage(userInfo.getUserId(), Constant.MSG_TYPE_TEXT, data); 
            
            //新用户注册奖励积分
            scoreService.rewardScore(userInfo.getUserId(), ScoreEnum.TYPE_USER_REGISTER);

            //根据ip地址绑定邀请人
            userService.autoInviter(userInfo);
            
            //事件回调
            long userId  = userInfo.getUserId();
            ThreadUtil.execAsync(() -> {
                JSONObject json  = new JSONObject();
                json.set("userId", userId);
                json.set("branch", param.getBranch());
                json.set("serial", param.getSerial());
                json.set("udid", param.getUdid());
                json.set("uagent", param.getUagent());
                json.set("ip", ip);
                HttpUtils.send_post_request("http://localhost:8183/callback/userRegister.php", null, JSONUtil.toJsonStr(json));
            });
        }
        else
        {
            // 更新邀请绑定状态
            userService.setInviteStatus(userInfo, Constant.INVITE_STATUS_BINDED);
        }

        // 更新用户登录信息
        UserLoginInfo loginInfo  = new UserLoginInfo();
        loginInfo.setLoginTime(now);
        loginInfo.setUserId(userInfo.getUserId());
        loginInfo.setBranch(param.getBranch());
        loginInfo.setVersion(param.getVersion());
        loginInfo.setModel(param.getModel());
        loginInfo.setBrand(param.getBrand());
        loginInfo.setSerial(param.getSerial());
        loginInfo.setUdid(param.getUdid());
        loginInfo.setAddr(ip);
        loginInfo.setUagent(param.getUagent());
        int ret  = accountService.saveLoginInfo(loginInfo, isNew);
        if (ret < 0)
        {
            throw new ApiException(ApiCodeEnum.SERVICE_ERROR);
        }

        LoginVO vo  = new LoginVO();
        KmsgDataDTO data  = authService.getKmsgData(userInfo.getUserId());
        vo.setKmsgToken(data.getToken());
        vo.setUserToken(authService.setUserToken(userInfo.getUserId(), true)); //登录时强制更新token
        vo.setUserInfo(BeanUtil.copyProperties(userInfo, UserInfoVO.class));
        
        //返回未结束的话单
        CallSheetInfo sheet  = getBusyCall(userInfo.getUserId());
        if (sheet != null)
        {
            vo.setCallSheet(sheet);
        }

        //无性别或无头像，并且无待审头像则要求上传头像
        if ((isNew == true) || (userInfo.getSex() == 0) || (((userInfo.getHeadUri() == null) || (userInfo.getHeadUri().equals(""))) && ((userInfo.getInfoStatus() & Constant.INFO_STATUS_HEAD) == 0)))
        {
            throw new ApiException(-10, "请上传头像或性别", vo);
        }
/*
        //登录发送系统公告
        ChatPrivateData notice;
        notice  = new ChatPrivateData();
        notice.setContent("请严格遵守《使用须知》中的相关规定，切勿发布违法违规信息");
        notice.setScheme("xinsu://web?url=https://wuxiu.cdks.net/web/protocol/notice.html");
        messageService.sendSystemMessage(userInfo.getUserId(), Constant.MSG_TYPE_NOTICE, notice);
*/
        return vo;
    }

    @ApiOperation("短信验证登录")
    @PostMapping("/smsLogin")
    public ApiResult<LoginVO> smsLogin(@RequestBody @Valid AccountSmsLoginParam param) {
        String phone  = param.getPhone();

        // 校验验证码
        commonService.checkSmsCode(phone, param.getCode());
        // 查询用户信息
        UserBaseInfo userInfo = userService.getUserByPhone(phone);

        return ApiResult.success(login(userInfo, phone, param));
    }

    @ApiOperation("一键登录")
    @PostMapping("/fastLogin")
    public ApiResult<LoginVO> fastLogin(@RequestBody @Valid AccountFastLoginParam param) {
        // 闪验获取手机号
        String phone = FlashMobileLoginUtil.getFlashMobilePhone(param.getCode(), param.getBranch());
        if (StrUtil.isBlank(phone)) {
            return ApiResult.failed(10, "手机号码获取失败");
        }
        // 查询用户信息
        UserBaseInfo userInfo = userService.getUserByPhone(phone);

        return ApiResult.success(login(userInfo, phone, param));
    }

    @ApiOperation("签名登录")
    @PostMapping("/signLogin")
    public ApiResult<LoginVO> signLogin(@RequestBody @Valid AccountSignLoginParam param) {
        return ApiResult.success(login(param.getUserInfo(), null, param));
    }

    @ApiOperation("退出登录")
    @PostMapping("/logout")
    public ApiResult<Object> logout(@RequestBody @Valid AuthParam param) {
        authService.delUserToken(param.getUserId());

        return ApiResult.success();
    }

    @ApiOperation("注销账号")
    @PostMapping("/delete")
    public ApiResult<Object> delete(@RequestBody @Valid AuthParam param) {
        
        authService.delUserToken(param.getUserId());
        accountService.deleteAccount(param.getUserInfo());

        //删除用户的云存数据
        CloudStorage.deleteUserData(param.getUserId());

        return ApiResult.success();
    }
}
